package com.inspur.edp.bef.bemanager.generatecomponent;


import com.inspur.edp.bef.bemanager.codegenerator.JavaCompCodeNames;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.component.json.ComponentConstantElement;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.entity.MetadataReference;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.util.ArrayList;

/**
 * 与元数据交互的工具
 */
public class GspMetadataExchangeUtil {
    public static GspMetadataExchangeUtil getInstance() {
        return new GspMetadataExchangeUtil();
    }

    private GspMetadataExchangeUtil() {
    }

    /**
     * 业务实体编号
     */
    private String privateBizEntityCode;

    private String getBizEntityCode() {
        return privateBizEntityCode;
    }

    private void setBizEntityCode(String value) {
        privateBizEntityCode = value;
    }

    /**
     * 元数据存放路径
     */
    private String privateMetadataPath;

    private String getMetadataPath() {
        return privateMetadataPath;
    }

    private void setMetadataPath(String value) {
        privateMetadataPath = value;
    }

    /**
     * 元数据名称
     */
    private String privateComponentName;

    private String getComponentName() {
        return privateComponentName;
    }

    private void setComponentName(String value) {
        privateComponentName = value;
    }

    /**
     * 是否是新建元数据
     */
    private boolean privateIsNewMetadata;

    private boolean getIsNewMetadata() {
        return privateIsNewMetadata;
    }

    private void setIsNewMetadata(boolean value) {
        privateIsNewMetadata = value;
    }

    private String privateBizObjectID;

    private String getBizObjectID() {
        return privateBizObjectID;
    }

    private void setBizObjectID(String value) {
        privateBizObjectID = value;
    }

    private String privateNameSpace;

    private String getNameSpace() {
        return privateNameSpace;
    }

    private void setNameSpace(String value) {
        privateNameSpace = value;
    }

    /**
     * 创建构件元数据，返回构件元数据ID
     *
     * @param component     构件实体
     * @param path          生成构件元数据的路径
     * @param bizEntityCode 业务实体编号
     * @return 生成的构件元数据名称
     * <see cref="string"/>
     */
    public final GspMetadata establishGspMetdadata(GspComponent component, String path, String bizEntityCode, String bizObjectID, String nameSpace) {
        this.setIsNewMetadata(true);
        this.setBizEntityCode(bizEntityCode);
        this.setMetadataPath(path);
        this.setBizObjectID(bizObjectID);
        this.setNameSpace(nameSpace);
        //1、构建元数据实体
        GspMetadata metadata = BuildGspMetadataEntity(component);
        //2、生成构件元数据
        return GenerateGspMetadata(metadata);
    }

    /**
     * 更新构件元数据
     *
     * @param component 构件实体
     * @param fullPath  要修改的构件元数据完整路径
     */
    public final void UpdateGspMetadata(GspComponent component, String fullPath, String bizEntityCode, String bizObjectID, String nameSpace) {
        this.setIsNewMetadata(false);
        this.setBizEntityCode(bizEntityCode);
        this.setBizObjectID(bizObjectID);
        FileService fileService = SpringBeanUtils.getBean(FileService.class);

        this.setMetadataPath(fileService.getDirectoryName(fullPath));
        this.setNameSpace(nameSpace);
        this.setComponentName(fileService.getFileNameWithoutExtension(fullPath));
        //1、构建元数据实体
        GspMetadata metadata = BuildGspMetadataEntity(component);
        UpdateComponentMetadata(metadata, fullPath);
    }

    ///#region 构建构件元数据实体

    /**
     * 创建GspMetadata实体
     *
     * @param component 构件实体
     * @return GspMetadata实体
     */
    private GspMetadata BuildGspMetadataEntity(GspComponent component) {
        GspMetadata metadata = CreateMetadataEntity();

        EvaluateMetadataHeader(component, metadata);
        EvaluateMetadataContent(component, metadata);
        return metadata;
    }

    /**
     * 创建元数据实例
     *
     * @return 实例化的元数据
     * <see cref="GspMetadata"/>
     */
    private GspMetadata CreateMetadataEntity() {
        GspMetadata tempVar = new GspMetadata();
        tempVar.setHeader(new MetadataHeader());
        tempVar.setRefs(new ArrayList<MetadataReference>());
        GspMetadata metadata = tempVar;
        return metadata;
    }

    /**
     * 为元数据的Header属性赋值
     *
     * @param component 构件实体
     * @param metadata  元数据实体
     */
    private void EvaluateMetadataHeader(GspComponent component, GspMetadata metadata) {
        if (CheckInfoUtil.checkNull(metadata.getHeader().getNameSpace())) {
            metadata.getHeader().setNameSpace(getNameSpace());
        }

        metadata.getHeader().setName(generateComponentMetadataName(component, this.getMetadataPath()));
        metadata.getHeader().setCode(generateComponentMetadataName(component, this.getMetadataPath()));
        metadata.getHeader().setFileName(this.getComponentName() + getCmpMetadataExtendNameByCompType(component.getComponentType()));
        metadata.getHeader().setType(getCmpMetadataTypeByCompType(component.getComponentType()));

        if (!CheckInfoUtil.checkNull(getBizObjectID())) {
            metadata.getHeader().setBizobjectID(getBizObjectID());
        }

        if (CheckInfoUtil.checkNull(metadata.getHeader().getId()) && CheckInfoUtil.checkNull(component.getComponentID())) //新建构件元数据时，需要初始化后获取ID
        {
            MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
            //初始化元数据，为了获取元数据ID
            metadata = metadataService.initializeMetadataEntity(metadata);
            component.setComponentID(metadata.getHeader().getId());
        } else if (CheckInfoUtil.checkNull(metadata.getHeader().getId()) && !CheckInfoUtil.checkNull(component.getComponentID())) //修改构件元数据时，需要为元数据的ID赋值
        {
            metadata.getHeader().setId(component.getComponentID());
        }
    }

    /**
     * 为元数据的Content属性赋值
     *
     * @param component 构件实体
     * @param metadata  元数据实体
     */
    private void EvaluateMetadataContent(GspComponent component, GspMetadata metadata) {
        metadata.setContent(component);
    }
    ///#region 根据元数据类型获取相应信息

    /**
     * 获取构件元数据拼接后缀名
     *
     * @param componentType 构件类型
     * @return
     */
    private String GetCmpMetadataExtendSuffixByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.BEMgrComponent:
        if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
            return JavaCompCodeNames.ActionMgrControllerName;
        }
//ORIGINAL LINE: case ComponentConstantElement.BEComponent:
        else if (componentType.equals(ComponentConstantElement.BEComponent)) {
            return JavaCompCodeNames.ActionControllerName;
        }
//ORIGINAL LINE: case ComponentConstantElement.DeterminationComponent:
        else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
            return JavaCompCodeNames.DeterminationControllerName;
        }
//ORIGINAL LINE: case ComponentConstantElement.ValidationComponent:
        else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
            return JavaCompCodeNames.ValidationControllerName;
        } else {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
        }
    }

    /**
     * 获取构件元数据扩展名
     *
     * @param componentType 构件类型
     * @return
     */
    private String getCmpMetadataExtendNameByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.BEMgrComponent:
        if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
            return JavaCompCodeNames.BEMgrCmpExtendName;
        }
//ORIGINAL LINE: case ComponentConstantElement.BEComponent:
        else if (componentType.equals(ComponentConstantElement.BEComponent)) {
            return JavaCompCodeNames.BECmpExtendName;
        }
//ORIGINAL LINE: case ComponentConstantElement.DeterminationComponent:
        else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
            return JavaCompCodeNames.DtmCmpExtendName;
        }
//ORIGINAL LINE: case ComponentConstantElement.ValidationComponent:
        else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
            return JavaCompCodeNames.ValCmpExtendName;
        } else {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
        }
    }

    /**
     * 获取构件元数据类型
     *
     * @param componentType 构件类型
     * @return
     */
    private String getCmpMetadataTypeByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.BEMgrComponent:
        if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
            return JavaCompCodeNames.BEMgrComponent;
        }
//ORIGINAL LINE: case ComponentConstantElement.BEComponent:
        else if (componentType.equals(ComponentConstantElement.BEComponent)) {
            return JavaCompCodeNames.BEComponent;
        }
//ORIGINAL LINE: case ComponentConstantElement.DeterminationComponent:
        else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
            return JavaCompCodeNames.DeterminationComponent;
        }
//ORIGINAL LINE: case ComponentConstantElement.ValidationComponent:
        else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
            return JavaCompCodeNames.ValidationComponent;
        } else {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
        }
    }

    ///#endregion

    ///#endregion

    /**
     * 生成构件元数据
     *
     * @param metadata 元数据
     * @param
     * @return 生成的构件元数据名称
     * <see cref="string"/>
     */
    private GspMetadata GenerateGspMetadata(GspMetadata metadata) {
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
        //创建元数据
        metadataService.createMetadata(this.getMetadataPath(), metadata);
        return metadata;
    }

    private void UpdateComponentMetadata(GspMetadata metadata, String fullPath) {
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

        metadataService.saveMetadata(metadata, fullPath);
    }

    /**
     * 生成当前路径下唯一的元数据名称
     *
     * @param component 构件实体
     * @param path      生成的元数据存放路径
     * @return 唯一的要生成的元数据名称
     */
    private String generateComponentMetadataName(GspComponent component, String path) {
        // 构件元数据命名规则
        String metadataFileName = this.getBizEntityCode() + component.getComponentCode() + GetCmpMetadataExtendSuffixByCompType(component.getComponentType());
        // 若为新增元数据操作，则需要检查路径下是否有重名元数据；若为修改元数据操作，则无需操作
        if (this.getIsNewMetadata()) {
            String orgMetadataFileName = metadataFileName;
            String metadataFileNameWithSuffix = metadataFileName + getCmpMetadataExtendNameByCompType(component.getComponentType());
            int index = 0;
            MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

            while (metadataService.isMetadataExist(path, metadataFileNameWithSuffix)) {
                //（同一个Be元数据中，若有重名，则自动增加后缀）
                metadataFileName = orgMetadataFileName + ++index;
                metadataFileNameWithSuffix = metadataFileName + getCmpMetadataExtendNameByCompType(component.getComponentType());
            }
            this.setComponentName(metadataFileName);
        }

        return metadataFileName;
    }
}